package de.swm.commons.mobile.client.widgets;

import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.dom.client.CanvasElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.ui.Image;import com.google.gwt.user.client.ui.Widget;import de.swm.commons.mobile.client.event.*;
import de.swm.commons.mobile.client.event.DragController;import de.swm.commons.mobile.client.event.DragEvent;
import de.swm.commons.mobile.client.event.DragEventsHandler;import de.swm.commons.mobile.client.utils.Utils;import java.lang.Override;import java.lang.String;

/**
 * Canvas element which is able to be painted with different colors and line widths.
 *
 * @author karsunke.franziskus
 *         <br> copyright (C) 2011, SWM Services GmbH
 */
public class PaintableCanvas extends Widget implements DragEventsHandler {

	public static final String STANDARD_COLOR = "black";
	public static final int STANDARD_LINE_WIDTH = 1;

	private static final String PIXEL_CSS = "px";

	private CanvasElement canvasElement;
	private Context2d context2d;

	private int lastX;
	private int lastY;

	private boolean inPaintMode = false;

	private String color;
	private int lineWidth;

	private int width;
	private int height;

	public PaintableCanvas(int height, int width) {
		super();

		canvasElement = Document.get().createCanvasElement();
		canvasElement.setId("paintableCanvas");

		this.setElement(canvasElement);

		this.setHeight(height);
		this.setWidth(width);
		this.color = STANDARD_COLOR;
		this.lineWidth = STANDARD_LINE_WIDTH;

		this.context2d = canvasElement.getContext2d();
		this.context2d.fill();


		this.context2d.setFillStyle("white");
		this.context2d.fillRect(0, 0, this.width, this.height);

		this.addDragHandler();
	}

	private void addDragHandler() {
		DragController.get().addDragEventsHandler(this);
	}

	private void onStart(int x, int y) {
		lastX = x;
		lastY = y;
		inPaintMode = true;
	}

	private void onMove(int x, int y) {
		if (inPaintMode) {
			paintLine(lastX, lastY, x, y);
			lastX = x;
			lastY = y;
		}
	}

	public void paintLine(int fromX, int fromY, int toX, int toY) {
		context2d.beginPath();
		context2d.moveTo(fromX, fromY);
		context2d.lineTo(toX, toY);
		context2d.setLineWidth(lineWidth);
		context2d.setStrokeStyle(this.color);
		context2d.stroke();
	}

	private void onEnd(int x, int y) {
		inPaintMode = false;
	}

	public void setHeight(int height) {
		this.setHeight(height + PIXEL_CSS);
		canvasElement.setHeight(height);
		this.height = height;
	}

	public void setWidth(int width) {
		this.setWidth(width + PIXEL_CSS);
		canvasElement.setWidth(width);
		this.width = width;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public int getLineWidth() {
		return lineWidth;
	}

	public void setLineWidth(int lineWidth) {
		this.lineWidth = lineWidth;
	}

	@Override
	public void onDragStart(DragEvent dragEvent) {

		onStart(dragEvent.getNativeEvent().getClientX() - this.getElement().getOffsetLeft(),
				dragEvent.getNativeEvent().getClientY() - this.getElement().getOffsetTop());
	}

	@Override
	public void onDragMove(DragEvent dragEvent) {
		onMove(dragEvent.getNativeEvent().getClientX() - this.getElement().getOffsetLeft(),
				dragEvent.getNativeEvent().getClientY() - this.getElement().getOffsetTop());
	}

	@Override
	public void onDragEnd(DragEvent dragEvent) {
		onEnd(dragEvent.getNativeEvent().getClientX() - this.getElement().getOffsetLeft(),
				dragEvent.getNativeEvent().getClientY() - this.getElement().getOffsetTop());
	}

	public String getImageAsBase64PNG() {
		return canvasElement.toDataUrl("image/png");
	}

	public void setImage(ImageResource resource) {
		this.drawImage(resource, 0, 0);
	}

	public void drawImage(ImageResource resource, int offsetX, int offsetY) {
		// load:
		SafeUri uri = resource.getSafeUri();
		ImageElement imgElement= ImageElement.as((new Image(uri)).getElement());

		// render
		context2d.drawImage(imgElement, offsetX, offsetY);
	}
}
